/* CJLib -- choices.c */


/* Routines to deal with loading, saving, and choosing new
 * preferences for the application
 */


/* from C lib: */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* from oslib */
#include "OSLib:os.h"
#include "OSLib:osfile.h"
#include "OSLib:messagetrans.h"


/* from library */
#include "etc.h"
#include "flex.h"
#include "message.h"
#include "choices.h"


#define MSG_BUFFER_SIZE 256


/* Generic function to save a choices file */


static void Choices_SaveTags (FILE *outfile, CJL_choices_tag *table)
{
  int i, j;
  unsigned int *up;
  int *ip;

  i = 0;
  while (table[i].token != NULL)
  {
    switch (table[i].type)
    {
      case TAGINT:
        fprintf (outfile, "%s:%d\n", table[i].token, *(int*)table[i].address);
        break;

      case TAGXINT:
        fprintf (outfile, "%s:%x\n", table[i].token, *(unsigned int*)table[i].address);
        break;

      case TAGSTR:
        fprintf (outfile, "%s:%s\n", table[i].token, table[i].address);
        break;

      case TAGBOOL:
        fprintf (outfile, "%s:%d\n", table[i].token, *(osbool*)table[i].address);
        break;

      case TAGDOUBLE:
        fprintf (outfile, "%s:%f\n", table[i].token, *(double*)table[i].address);
        break;

      case TAGINT_A:
        fprintf (outfile, "%s:", table[i].token);
        ip = (int*)table[i].address;
        for (j = 0; j < table[i].array_size; j++)
        {
          fprintf (outfile, "%d ", *(ip + j));
        }
        fprintf (outfile, "\n");
        break;

      case TAGXINT_A:
        fprintf (outfile, "%s:", table[i].token);
        up = (unsigned int*)table[i].address;
        for (j = 0; j < table[i].array_size; j++)
        {
          fprintf (outfile, "%x ", *(up + j));
        }
        fprintf (outfile, "\n");
        break;

    }
    i++;
  }
  return;
}



static void Choices_LoadTags (messagetrans_control_block *cb, CJL_choices_tag *table)
{
  os_error *err;
  char msg_buffer[MSG_BUFFER_SIZE];
  int returned_msg_size ;
  char *result = NULL ;
  int i;
  int j;
  char *p, *p1, *sp;
  int len;

  i = 0;
  while (table[i].token != NULL)
  {
    err = xmessagetrans_lookup (cb,
                                table[i].token,
                                msg_buffer,
                                MSG_BUFFER_SIZE ,
                                0, 0, 0, 0,
                                &result,
                                &returned_msg_size ) ;
    if ( (err == NULL) && (returned_msg_size > 0) )
    {
      switch (table[i].type)
      {
        case TAGINT:
          *(int*)table[i].address  = atoi (msg_buffer) ;
          break;

        case TAGXINT:
          *(int*)table[i].address  = (int)strtoul ( msg_buffer, NULL, 16 ) ;
          break;

        case TAGSTR:
          strcpy (table[i].address, msg_buffer);
          break;

        case TAGDOUBLE:
          *(double*)table[i].address  = atof (msg_buffer) ;
          break;

        case TAGBOOL:
          *(osbool*)table[i].address  = ( atoi (msg_buffer) != 0);
          break;

        case TAGINT_A:
          j = 0;
          p = msg_buffer;
          len = strlen (p);

          while (( len > 0) && (j < table[i].array_size))
          {
            sp = strchr (p, ' ');
            if (sp) *sp = 0x00;
            *(((int*)table[i].address) + j)  = atoi (p) ;
            j++;
            if (sp) p = sp + 1;
            else p += len + 1;
            len = strlen (p);
          }
          break;

        case TAGXINT_A:
          j = 0;
          p = msg_buffer;
          len = strlen (p);

          while (( len > 0) && (j < table[i].array_size))
          {
            sp = strchr (p, ' ');
            if (sp) *sp = 0x00;
            *(((int*)table[i].address) + j)  = (int)strtoul (p, NULL, 16) ;
            j++;
            if (sp) p = sp + 1;
            else p += len + 1;
            len = strlen (p);
          }
          break;
      }
    }
    i++;
  }

  return;
}



#define FNAME_BUF_SIZE 256

osbool CJL_ChoicesMakeFilename (CJL_choices_loadsavedata *d, char *full_filename)

{
  os_error   *err;
  int         used;
  int         context_out;
  os_var_type var_type_out;
////  char       *dir;

  /* find if we have a choices write path */
  err = xos_read_var_val_size ("Choices$Write",0,0,&used,&context_out,
                               &var_type_out );
  if ((used == 0) || err)
  {
    /* variable does not exist - use the app directory in that case */
    sprintf ( full_filename, "<%s$Dir>.%s", d->app_name, d->leafname);
  }
  else
  {
    /* variable does exist so use choices path */
    if (d->save)
    {
      /* first ensure our directory exists by creating it */
        strcpy (full_filename, "<Choices$Write>.");
        if (strcmp (d->author_dir, ""))
        {
          strcat (full_filename, d->author_dir);
          err = xosfile_create_dir (full_filename, 0);
          // now convert to path
          strcat (full_filename, ".");
        }
        /* now add the app name and create the directory */
        strcat (full_filename, d->app_name);
        err = xosfile_create_dir (full_filename, 0);
        strcat (full_filename, ".");
        strcat (full_filename, d->leafname);
    }
    else
    {
      // we are reading the file
      strcpy (full_filename, "Choices:");
      if (strcmp (d->author_dir, ""))
      {
        strcat (full_filename, d->author_dir);
        strcat (full_filename, ".");
      }
      strcat (full_filename, d->app_name);
      strcat (full_filename, ".");
      strcat (full_filename, d->leafname);
    }
    /* In full version check for choices file inside application */
  }
  return (TRUE);
}



void CJL_ChoicesSave (CJL_choices_loadsavedata *d, CJL_choices_tag *table)
{
  FILE  *outfile;
  char  filename[256] ;
  time_t current ;
  struct tm *converted_time ;
  size_t length ;
  size_t maxsize = 128 ;
  char   t[128] ;


  if (CJL_ChoicesMakeFilename (d, filename))
  {
    outfile = fopen (filename, "w" ) ;
    if (outfile == NULL)
    {
      /* file would not open or create */
      CJL_MsgWarnF ( d->data.save.write_err, "Could not open choices file" ) ;
      return;
    }
    else
    {
      fprintf (outfile, "# %s file written by %s\n", d->file_id, d->app_name) ;
      /* now get the time and convert to suitable format */
      current = time (NULL) ;
      converted_time = localtime (&current) ;
      length = strftime (t, maxsize, "# Written at %H:%M:%S on %d %b %Y",
                                            converted_time) ;
      /* now write the time to file */
      fprintf (outfile, "%s\n", t) ;
      fprintf (outfile, "# Autogenerated by %s - unwise to edit\n\n", d->app_name);
      /* now put the choices data into the file */
      Choices_SaveTags (outfile, table);

      /* Finished - close the file */
      fclose (outfile) ;
      osfile_set_type (filename, osfile_TYPE_TEXT) ;

    }
  }

}



void CJL_ChoicesLoad (CJL_choices_loadsavedata *d, CJL_choices_tag *table)
{
  char  filename[256] ;
  messagetrans_file_flags flags ;
  int file_size;
  messagetrans_control_block cb ;
  char *buffer;
  osbool mem_ok;

  if (!CJL_ChoicesMakeFilename (d, filename)) return;

  if (xmessagetrans_file_info ( filename, &flags, &file_size ))
  {
    /* Do not give an error message - just return quietly */
    return;
  }

  /* allocate buffer for file */
  file_size += 8;
  if (d->use_flex)
  {
    mem_ok = FLEXALLOC(buffer,file_size);
  }
  else
  {
    buffer = (char *)malloc(file_size);
    mem_ok = (buffer != NULL);
  }
  if (!mem_ok)
  {
    /* cannot allocate the required memory */
    CJL_MsgWarnF ( d->data.load.malloc_fail,
                          "No memory to load choices file" );
    return;
  }

  if (xmessagetrans_open_file ( &cb, filename, buffer ))
  {
    /* err message and return */
    CJL_MsgWarnF ( d->data.load.no_read,
                          "Choices file could not be opened for read" );
    goto finish;
  }
  else
  {
    /* extract the data from the file */
    Choices_LoadTags (&cb, table);
  }

  messagetrans_close_file (&cb) ;

  finish:

  if (d->use_flex)
  {
    FLEXFREE(buffer);
  }
  else
  {
    free(buffer);
  }
  return;
}







